/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.model;

import java.io.Serializable;

import javax.persistence.Embedded;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.google.code.sapien.security.CategoryPermissions;

/**
 * Category Access Control List, used to control access to categories.
 * @author Adam
 * @version $Id: CategoryAcl.java 30 2010-01-10 19:05:55Z a.ruggles $
 * 
 * Created on Mar 6, 2009 at 8:36:36 PM 
 */
@javax.persistence.Entity
@Table(name = "sapien_category_acls",
		uniqueConstraints = {@UniqueConstraint(columnNames = {"category_id", "role_id" }) })
@NamedQueries({
	@NamedQuery(name = "categoryAcl.getCategoryRole",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl "
				+ "WHERE acl.category.id = :categoryId and acl.role.id = :roleId"),
	@NamedQuery(name = "categoryAcl.listCategory",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl "
				+ "WHERE acl.category.id = :categoryId"),
	@NamedQuery(name = "categoryAcl.listRoles",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl "
				+ "WHERE acl.role IN (:roles) order by acl.category, acl.role"),
	@NamedQuery(name = "categoryAcl.listRole",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl WHERE acl.role.id = :roleId"),
	@NamedQuery(name = "categoryAcl.listForGuests",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl "
				+ "WHERE acl.role.guestDefault = true"),
	@NamedQuery(name = "categoryAcl.listForNewUsers",
			query = "SELECT acl FROM com.google.code.sapien.model.CategoryAcl AS acl "
				+ "WHERE acl.role.userDefault = true")
})
public class CategoryAcl implements Serializable {
    /**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = 2262853692273794873L;

	/**
     * The category this entry is assigned to.
     */
    private Category category = new Category();

    /**
     * Unique identifier.
     */
    private Long id;

    /**
     * The permissions that govern the access.
     */
    private CategoryPermissions permissions = new CategoryPermissions();

    /**
     * The role this entry is assigned to.
     */
    private Role role = new Role();

    /**
     * Default constructor.
     */
    public CategoryAcl() { }

    /**
     * Constructs a Category ACL.
     * @param category The category.
     * @param role The role.
     * @param permissions The category permissions.
     */
    public CategoryAcl(final Category category, final Role role, final CategoryPermissions permissions) {
    	this.category = category;
    	this.role = role;
    	this.permissions = permissions;
    }

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof CategoryAcl)) {
			return false;
		}
		final CategoryAcl rhs = (CategoryAcl) obj;
		return new EqualsBuilder()
			.append(category.getId(), rhs.getCategory().getId())
			.append(role.getId(), rhs.getRole().getId())
			.append(permissions, rhs.getPermissions())
			.isEquals();
	}

	/**
	 * Returns category.
	 * @return the category.
	 */
	@ManyToOne(fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "category_id")
	public Category getCategory() {
		return category;
	}

	/**
	 * Returns id.
	 * @return the id.
	 */
	@Id @GeneratedValue(strategy = GenerationType.AUTO)
	public Long getId() {
		return id;
	}

	/**
	 * Returns permissions.
	 * @return the permissions.
	 */
	@Embedded
	public CategoryPermissions getPermissions() {
		return permissions;
	}

	/**
	 * Returns role.
	 * @return the role.
	 */
	@ManyToOne(fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "role_id")
	public Role getRole() {
		return role;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(5, 11)
			.append(category.getId())
			.append(role.getId())
			.append(permissions)
			.toHashCode();
	}

	/**
	 * Sets category.
	 * @param category the category to set.
	 */
	public void setCategory(final Category category) {
		this.category = category;
	}

	/**
	 * Sets id.
	 * @param id the id to set.
	 */
	public void setId(final Long id) {
		this.id = id;
	}

	/**
	 * Sets permissions.
	 * @param permissions the permissions to set.
	 */
	public void setPermissions(final CategoryPermissions permissions) {
		this.permissions = permissions;
	}

	/**
	 * Sets role.
	 * @param role the role to set.
	 */
	public void setRole(final Role role) {
		this.role = role;
	}

	/**
	 * Returns a JSON object representing this object in JavaScript.
	 * @return A String.
	 */
	public String toJSON() {
		return new StringBuilder("{")
			.append("id:").append(id)
			.append(",categoryId:").append(category.getId())
			.append(",roleId:").append(role.getId())
			.append(",canAddDiscussion:").append(permissions.isCanAddDiscussion())
			.append(",canAddResponse:").append(permissions.isCanAddResponse())
			.append(",canEditDiscussion:").append(permissions.isCanEditDiscussion())
			.append(",canEditResponse:").append(permissions.isCanEditResponse())
			.append(",canRemoveDiscussion:").append(permissions.isCanRemoveDiscussion())
			.append(",canRemoveResponse:").append(permissions.isCanRemoveResponse())
			.append(",canSetLock:").append(permissions.isCanSetLock())
			.append(",canSetSticky:").append(permissions.isCanSetSticky())
			.append('}').toString();
		
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new ToStringBuilder(this)
			.append("id", id)
			.append("categoryId", category.getId())
			.append("roleId", role.getId())
			.append("permissions", permissions)
			.toString();
	}
}
